/* eslint-disable */
/*
* A JavaScript implementation of the SHA256 hash function.
*
* FILE:	sha256.js
* VERSION:	0.8
* AUTHOR:	Christoph Bichlmeier <informatik@zombiearena.de>
*
* NOTE: This version is not tested thoroughly!
*
* Copyright (c) 2003, Christoph Bichlmeier
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
*    notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
*    notice, this list of conditions and the following disclaimer in the
*    documentation and/or other materials provided with the distribution.
* 3. Neither the name of the copyright holder nor the names of contributors
*    may be used to endorse or promote products derived from this software
*    without specific prior written permission.
*
* ======================================================================
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''AS IS'' AND ANY EXPRESS
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

/* SHA256 logical functions */
function rotateRight (n, x) {
    return ((x >>> n) | (x << (32 - n)));
}
function choice (x, y, z) {
    return ((x & y) ^ (~x & z));
}
function majority (x, y, z) {
    return ((x & y) ^ (x & z) ^ (y & z));
}
function sha256_Sigma0 (x) {
    return (rotateRight(2, x) ^ rotateRight(13, x) ^ rotateRight(22, x));
}
function sha256_Sigma1 (x) {
    return (rotateRight(6, x) ^ rotateRight(11, x) ^ rotateRight(25, x));
}
function sha256_sigma0 (x) {
    return (rotateRight(7, x) ^ rotateRight(18, x) ^ (x >>> 3));
}
function sha256_sigma1 (x) {
    return (rotateRight(17, x) ^ rotateRight(19, x) ^ (x >>> 10));
}
function sha256_expand (W, j) {
    return (W[j & 0x0f] += sha256_sigma1(W[(j + 14) & 0x0f]) + W[(j + 9) & 0x0f] +
sha256_sigma0(W[(j + 1) & 0x0f]));
}

/* Hash constant words K: */
var K256 = new Array(
    0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5,
    0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
    0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
    0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
    0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc,
    0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
    0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7,
    0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
    0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
    0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
    0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3,
    0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
    0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5,
    0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
    0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
    0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
);

/* global arrays */
var ihash, count, buffer;
var sha256_hex_digits = '0123456789abcdef';

/* Add 32-bit integers with 16-bit operations (bug in some JS-interpreters:
overflow) */
function safe_add (x, y) {
    var lsw = (x & 0xffff) + (y & 0xffff);
    var msw = (x >> 16) + (y >> 16) + (lsw >> 16);
    return (msw << 16) | (lsw & 0xffff);
}

/* Initialise the SHA256 computation */
function sha256_init () {
    ihash = new Array(8);
    count = new Array(2);
    buffer = new Array(64);
    count[0] = count[1] = 0;
    ihash[0] = 0x6a09e667;
    ihash[1] = 0xbb67ae85;
    ihash[2] = 0x3c6ef372;
    ihash[3] = 0xa54ff53a;
    ihash[4] = 0x510e527f;
    ihash[5] = 0x9b05688c;
    ihash[6] = 0x1f83d9ab;
    ihash[7] = 0x5be0cd19;
}

/* Transform a 512-bit message block */
function sha256_transform () {
    var a, b, c, d, e, f, g, h, T1, T2;
    var W = new Array(16);

    /* Initialize registers with the previous intermediate value */
    a = ihash[0];
    b = ihash[1];
    c = ihash[2];
    d = ihash[3];
    e = ihash[4];
    f = ihash[5];
    g = ihash[6];
    h = ihash[7];

    /* make 32-bit words */
    for (var i = 0;i < 16;i++) {
        W[i] = ((buffer[(i << 2) + 3]) | (buffer[(i << 2) + 2] << 8) | (buffer[(i << 2) + 1] <<
16) | (buffer[i << 2] << 24));
    }

    for (var j = 0;j < 64;j++) {
        T1 = h + sha256_Sigma1(e) + choice(e, f, g) + K256[j];
        if (j < 16) T1 += W[j];
        else T1 += sha256_expand(W, j);
        T2 = sha256_Sigma0(a) + majority(a, b, c);
        h = g;
        g = f;
        f = e;
        e = safe_add(d, T1);
        d = c;
        c = b;
        b = a;
        a = safe_add(T1, T2);
    }

    /* Compute the current intermediate hash value */
    ihash[0] += a;
    ihash[1] += b;
    ihash[2] += c;
    ihash[3] += d;
    ihash[4] += e;
    ihash[5] += f;
    ihash[6] += g;
    ihash[7] += h;
}

/* Read the next chunk of data and update the SHA256 computation */
function sha256_update (data, inputLen) {
    var i, index, curpos = 0;
    /* Compute number of bytes mod 64 */
    index = ((count[0] >> 3) & 0x3f);
    var remainder = (inputLen & 0x3f);

    /* Update number of bits */
    if ((count[0] += (inputLen << 3)) < (inputLen << 3)) count[1]++;
    count[1] += (inputLen >> 29);

    /* Transform as many times as possible */
    for (i = 0;i + 63 < inputLen;i += 64) {
        for (var j = index;j < 64;j++) { buffer[j] = data.charCodeAt(curpos++); }
        sha256_transform();
        index = 0;
    }

    /* Buffer remaining input */
    for (var j = 0;j < remainder;j++) { buffer[j] = data.charCodeAt(curpos++); }
}

/* Finish the computation by operations such as padding */
function sha256_final () {
    var index = ((count[0] >> 3) & 0x3f);
    buffer[index++] = 0x80;
    if (index <= 56) {
        for (var i = index;i < 56;i++) { buffer[i] = 0; }
    } else {
        for (var i = index;i < 64;i++) { buffer[i] = 0; }
        sha256_transform();
        for (var i = 0;i < 56;i++) { buffer[i] = 0; }
    }
    buffer[56] = (count[1] >>> 24) & 0xff;
    buffer[57] = (count[1] >>> 16) & 0xff;
    buffer[58] = (count[1] >>> 8) & 0xff;
    buffer[59] = count[1] & 0xff;
    buffer[60] = (count[0] >>> 24) & 0xff;
    buffer[61] = (count[0] >>> 16) & 0xff;
    buffer[62] = (count[0] >>> 8) & 0xff;
    buffer[63] = count[0] & 0xff;
    sha256_transform();
}

/* Split the internal hash values into an array of bytes */
function sha256_encode_bytes () {
    var j = 0;
    var output = new Array(32);
    for (var i = 0;i < 8;i++) {
        output[j++] = ((ihash[i] >>> 24) & 0xff);
        output[j++] = ((ihash[i] >>> 16) & 0xff);
        output[j++] = ((ihash[i] >>> 8) & 0xff);
        output[j++] = (ihash[i] & 0xff);
    }
    return output;
}

/* Get the internal hash as a hex string */
function sha256_encode_hex () {
    var output = new String();
    for (var i = 0;i < 8;i++) {
        for (var j = 28;j >= 0;j -= 4) { output += sha256_hex_digits.charAt((ihash[i] >>> j) & 0x0f); }
    }
    return output;
}

/* Main function: returns a hex string representing the SHA256 value of the
given data */
function sha256_digest (data) {
    sha256_init();
    sha256_update(data, data.length);
    sha256_final();
    return sha256_encode_hex();
}

/* test if the JS-interpreter is working properly */
function sha256_self_test () {
    return sha256_digest('message digest') ==
'f7846f55cf23e14eebeab5b4e1550cad5b509e3348fbc4efa3a1413d393cb650';
}





/**
 * 
 * 
 * 
file input表单上传

var reader = new FileReader();
	reader.onload = function(e) {
		return text = reader.result;		
		(1)调用SCloudLightSDK.makeSha256计算sha56
		(2)计算数字签名
		   action 及SCloudLightSDK.uploadAndSubmit的入口参数， 
		   sha256,timestamp,accessKeyId,appId,pub,suffix,clientIp,location,trace_reserve_mark		
		   在计算数字签名时，如非空，必须被签进去，否则验证时通不过
		 			   
		(3)调用SCloudLightSDK.uploadAndSubmit上传
	}
reader.readAsBinaryString(selected_file, "utf-8");
	
 */

var SCloudLightSDK = window.SCloudLightSDK || {};
/**
 * 云存储独特的sha256字符集
 */
SCloudLightSDK.base64EncodeChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-";
/**
 * 云存储独特的sha256算法，见云存储用户手册
 */
SCloudLightSDK.makeSha256=function(text) {		
		return SCloudLightSDK.base16to64(sha256_digest(text));			
}

/**
 * 云存储业务追溯Mark生成算法
 */
SCloudLightSDK.makeUUID=function() {
	var s = [];
	var hexDigits = "0123456789abcdef";
	for (var i = 0; i < 36; i++) {
		s[i] = hexDigits.substr(Math.floor(Math.random() * 0x10), 1);
	}
	s[14] = "4"; // bits 12-15 of the time_hi_and_version field to 0010
	s[19] = hexDigits.substr((s[19] & 0x3) | 0x8, 1); // bits 6-7 of the clock_seq_hi_and_reserved to 01
	s[8] = s[13] = s[18] = s[23] = "-";

	var uuid = s.join("");
	return uuid;
}

/**
 * 功能 云存储file 表单上传文件 
 * selected_file document.getElementById('input').files[0]或 jquery $获取的file输入表单对象
 * sha256 云存储独特的sha256,调用SCloudLightSDK.makeSha256计算; 
 * signature数字签名 signature将请求串的非文件流的部分及action 用海明码账户密码签名，具体算法参见用户手册，从安全角度不建议前台做签名，后台计算数字签名的时候可以调用云存储SDK; 
 * timestamp时间戳long整形，(new Date()).getTime(); 
 * accessKeyId，租户名，如'toon';
 * appId租户ID，如1001;
 * clientIp客户端IP "127.0.0.1"; 
 * location经纬度，例如"111.132,123.123"; 
 * pub是否公开，"1"：公开，"0":私有; 
 * suffix 文件后缀如 ".jpg"
 * trace_reserve_mark 业务追溯mark makeUUID(); 
 * length 流字节长度，取selected_file.size;
 * uploadCallback上传回调方法，方法入口为json对象
 */

SCloudLightSDK.uploadFile=function(url,selected_file,sha256,signature,timestamp,accessKeyId,appId,pub,suffix,clientIp,location,trace_reserve_mark,length,uploadCallback,err) {
	
	            var length = selected_file.size;
				var formData  =  new FormData();
				
				formData.append("length", length);
				formData.append("sha256", sha256);
				formData.append("signature", signature);
				formData.append("timestamp", timestamp);
				formData.append("accessKeyId", accessKeyId);
				formData.append("appId", appId);
				
				formData.append("clientIp", clientIp);
				formData.append("location", location);
				formData.append("pub", pub);
				formData.append("suffix", suffix);
				formData.append("length", length);
				formData.append("trace_reserve_mark", trace_reserve_mark);
				formData.append("file", selected_file);
				
				$.ajax({
					url : url+'/jsUploadFile',
					type : 'POST',
					data : formData,
					async : false,
					cache : false,
					contentType : false,
					processData : false,
					success : uploadCallback,
					error :err|| function(returndata) {
						return returndata;
					}
				});			
				return null;
}



/**
 * 功能 云存储mblob表单上传文件 
 * mblob,从base64串及mimetype SCloudLightSDK.mblobFromBase64AndMimeType
 * signature数字签名 signature将请求串的非文件流的部分及action 用海明码账户密码签名，具体算法参见用户手册，从安全角度不建议前台做签名，后台计算数字签名的时候可以调用云存储SDK; 
 * timestamp时间戳long整形，(new Date()).getTime(); 
 * accessKeyId，租户名，如'toon';
 * appId租户ID，如1001;
 * clientIp客户端IP "127.0.0.1"; 
 * location经纬度，例如"111.132,123.123"; 
 * pub是否公开，"1"：公开，"0":私有; 
 * suffix 文件后缀如 ".jpg"
 * trace_reserve_mark 业务追溯mark makeUUID(); 
 * length 流字节长度，取selected_file.size;
 * uploadCallback上传回调方法，方法入口为json对象
 */
 
SCloudLightSDK.uploadMBlob=function(url,mblob,signature,timestamp,accessKeyId,appId,clientIp,location,pub,suffix,trace_reserve_mark,uploadCallback) {
		            
				var formData  =  new FormData();
				formData.append("length", mblob.length);
				formData.append("sha256", mblob.sha256);
				formData.append("signature", signature);
				formData.append("timestamp", timestamp);
				formData.append("accessKeyId", accessKeyId);
				formData.append("appId", appId);
				
				formData.append("clientIp", clientIp);
				formData.append("location", location);
				formData.append("pub", pub);
				formData.append("suffix", suffix);
				formData.append("length", length);
				formData.append("trace_reserve_mark", trace_reserve_mark);
				formData.append("file", mblob.blob);
				
				$.ajax({
					url : url+'/jsUploadFile',
					type : 'POST',
					data : formData,
					async : false,
					cache : false,
					contentType : false,
					processData : false,
					success : uploadCallback,
					error : function(returndata) {
						return returndata;
					}
				});			
				return null;
}


SCloudLightSDK.getIndex = function(c) {
	if (c < 65)
		return c - 48;
	return c - 97 + 10;
}

SCloudLightSDK.base16to64 = function(str) {
	var out, i, len, c1, c2, c3, t;
	out = "";
	len = str.length;
	i = 0;
	var count = 0;
	while (i < len) {
		if (i + 3 < len) {
			c1 = SCloudLightSDK.getIndex(str.charCodeAt(i++));
			c2 = SCloudLightSDK.getIndex(str.charCodeAt(i++));
			c3 = SCloudLightSDK.getIndex(str.charCodeAt(i++));
			t = (c1) * 16 * 16 + (c2) * 16 + (c3);
			var indexa, indexb;
			indexa = parseInt(t / 64);
			indexb = parseInt(t % 64);

			out += SCloudLightSDK.base64EncodeChars.charAt(indexa);
			out += SCloudLightSDK.base64EncodeChars.charAt(indexb);
			count += 2;

		} else {
			c1 = SCloudLightSDK.getIndex(str.charCodeAt(i++));
			c1 = c1 * 4;
			out += SCloudLightSDK.base64EncodeChars.charAt(c1 % 64);
			count += 1;
			// alert("last:"+base64EncodeChars.charAt(c1 % 64));
		}
	}
	// alert("count:"+count);
	// alert("out:"+out.length);

	return out;
}




/**
 * 从文件base64，mimeString获取blob扩展对象
 * 返回
 * {
		length:byteString.length,
		blob:blob,
		sha256:sha256
	} 对象
 */
SCloudLightSDK.mblobFromBase64AndMimeType = function(data,mimeString) {
  
//	var byteString = window.decodeURIComponent(window
//			.atob(data));// base64 解码
	var byteString = window.atob(data);// base64 解码
	var arrayBuffer = new ArrayBuffer(byteString.length); // 创建缓冲数组
	var intArray = new Uint8Array(arrayBuffer); // 创建视图
	for (i = 0; i < byteString.length; i += 1) {
		intArray[i] = byteString.charCodeAt(i);
	}
	var blob = new Blob([ intArray ], {
		type : mimeString
	}); // 转成blob	
	var sha256=SCloudLightSDK.makeSha256(byteString);
	return {
		length:byteString.length,
		blob:blob,
		sha256:sha256
		};
};

export default SCloudLightSDK;

